package com.apikey.auth.service.impl;

import com.apikey.auth.entity.ApiKey;
import com.apikey.auth.service.ApiKeyService;
import com.apikey.auth.validator.ApiKeyPermissionValidator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 默认的API Key权限验证器实现
 * 提供基础的权限验证功能，可以被自定义实现替换
 *
 * @author API Key Framework
 * @version 1.0
 */
@Component
public class DefaultApiKeyPermissionValidator implements ApiKeyPermissionValidator {

    @Autowired
    private ApiKeyService apiKeyService;

    // 系统预定义的权限列表
    private static final Map<String, String> AVAILABLE_PERMISSIONS = new HashMap<>();

    // 路径权限映射
    private static final Map<String, Set<String>> PATH_PERMISSIONS = new HashMap<>();

    static {
        // 初始化可用权限
        AVAILABLE_PERMISSIONS.put("*", "所有权限");
        AVAILABLE_PERMISSIONS.put("read", "读取权限");
        AVAILABLE_PERMISSIONS.put("write", "写入权限");
        AVAILABLE_PERMISSIONS.put("delete", "删除权限");
        AVAILABLE_PERMISSIONS.put("admin", "管理权限");
        AVAILABLE_PERMISSIONS.put("user.read", "用户读取权限");
        AVAILABLE_PERMISSIONS.put("user.write", "用户写入权限");
        AVAILABLE_PERMISSIONS.put("user.delete", "用户删除权限");
        AVAILABLE_PERMISSIONS.put("api.read", "API读取权限");
        AVAILABLE_PERMISSIONS.put("api.write", "API写入权限");
        AVAILABLE_PERMISSIONS.put("api.delete", "API删除权限");
        AVAILABLE_PERMISSIONS.put("file.read", "文件读取权限");
        AVAILABLE_PERMISSIONS.put("file.write", "文件写入权限");
        AVAILABLE_PERMISSIONS.put("file.delete", "文件删除权限");

        // 初始化路径权限映射
        Set<String> userReadSet = new HashSet<>();
        userReadSet.add("user.read");
        userReadSet.add("read");
        PATH_PERMISSIONS.put("/api/users", userReadSet);
        PATH_PERMISSIONS.put("/api/users/*", userReadSet);

        Set<String> fileReadSet = new HashSet<>();
        fileReadSet.add("file.read");
        fileReadSet.add("read");
        PATH_PERMISSIONS.put("/api/files", fileReadSet);
        PATH_PERMISSIONS.put("/api/files/*", fileReadSet);

        Set<String> adminSet = new HashSet<>();
        adminSet.add("admin");
        PATH_PERMISSIONS.put("/api/admin", adminSet);
        PATH_PERMISSIONS.put("/api/admin/*", adminSet);
    }

    /**
     * 验证API Key是否有访问指定资源的权限
     */
    @Override
    public boolean hasPermission(String apiKeyValue, String resource, String action) {
        Optional<ApiKey> apiKeyOpt = apiKeyService.findByKeyValue(apiKeyValue);
        if (!apiKeyOpt.isPresent()) {
            return false;
        }

        ApiKey apiKey = apiKeyOpt.get();
        if (!apiKeyService.validateApiKey(apiKeyValue)) {
            return false;
        }

        List<String> permissions = getPermissions(apiKeyValue);

        // 检查通配符权限
        if (permissions.contains("*")) {
            return true;
        }

        // 检查具体权限
        String requiredPermission = resource + "." + action;
        if (permissions.contains(requiredPermission)) {
            return true;
        }

        // 检查通用权限
        if (permissions.contains(action)) {
            return true;
        }

        // 检查资源级权限
        if (permissions.contains(resource)) {
            return true;
        }

        return false;
    }

    /**
     * 验证API Key是否有访问指定路径的权限
     */
    @Override
    public boolean hasPathPermission(String apiKeyValue, String requestPath, String httpMethod) {
        Optional<ApiKey> apiKeyOpt = apiKeyService.findByKeyValue(apiKeyValue);
        if (!apiKeyOpt.isPresent()) {
            return false;
        }

        if (!apiKeyService.validateApiKey(apiKeyValue)) {
            return false;
        }

        List<String> permissions = getPermissions(apiKeyValue);

        // 检查通配符权限
        if (permissions.contains("*")) {
            return true;
        }

        // 根据HTTP方法确定所需权限
        String requiredAction = getActionByHttpMethod(httpMethod);

        // 检查路径特定权限
        Set<String> pathPermissions = getPathPermissions(requestPath);
        for (String pathPermission : pathPermissions) {
            if (permissions.contains(pathPermission)) {
                return true;
            }
        }

        // 检查通用操作权限
        if (permissions.contains(requiredAction)) {
            return true;
        }

        return false;
    }

    /**
     * 获取API Key的所有权限列表
     */
    @Override
    public List<String> getPermissions(String apiKeyValue) {
        Optional<ApiKey> apiKeyOpt = apiKeyService.findByKeyValue(apiKeyValue);
        if (!apiKeyOpt.isPresent()) {
            return Collections.emptyList();
        }

        ApiKey apiKey = apiKeyOpt.get();
        String permissions = apiKey.getPermissions();

        return parsePermissions(permissions);
    }

    /**
     * 获取API Key可访问的资源列表
     */
    @Override
    public Set<String> getAccessibleResources(String apiKeyValue) {
        List<String> permissions = getPermissions(apiKeyValue);
        Set<String> resources = new HashSet<>();

        for (String permission : permissions) {
            if ("*".equals(permission)) {
                // 通配符权限可以访问所有资源
                resources.addAll(extractResourcesFromPermissions());
                break;
            }

            // 提取资源名称
            if (permission.contains(".")) {
                String resource = permission.substring(0, permission.lastIndexOf("."));
                resources.add(resource);
            } else {
                // 通用权限
                resources.add(permission);
            }
        }

        return resources;
    }

    /**
     * 验证权限字符串格式是否正确
     */
    @Override
    public boolean isValidPermissionFormat(String permissions) {
        if (permissions == null || permissions.trim().isEmpty()) {
            return true; // 空权限是有效的
        }

        String[] permissionArray = permissions.split(",");
        for (String permission : permissionArray) {
            String trimmed = permission.trim();
            if (trimmed.isEmpty()) {
                return false;
            }

            // 检查权限格式：只能包含字母、数字、点号、星号
            if (!trimmed.matches("^[a-zA-Z0-9.*_-]+$")) {
                return false;
            }
        }

        return true;
    }

    /**
     * 解析权限字符串为权限列表
     */
    @Override
    public List<String> parsePermissions(String permissions) {
        if (permissions == null || permissions.trim().isEmpty()) {
            return Collections.emptyList();
        }

        return Arrays.stream(permissions.split(","))
                .map(String::trim)
                .filter(p -> !p.isEmpty())
                .collect(Collectors.toList());
    }

    /**
     * 将权限列表转换为权限字符串
     */
    @Override
    public String formatPermissions(List<String> permissions) {
        if (permissions == null || permissions.isEmpty()) {
            return "";
        }

        return permissions.stream()
                .filter(Objects::nonNull)
                .map(String::trim)
                .filter(p -> !p.isEmpty())
                .collect(Collectors.joining(","));
    }

    /**
     * 验证权限是否存在于系统中
     */
    @Override
    public boolean isValidPermission(String permission) {
        if (permission == null || permission.trim().isEmpty()) {
            return false;
        }

        String trimmed = permission.trim();

        // 通配符权限总是有效的
        if ("*".equals(trimmed)) {
            return true;
        }

        // 检查预定义权限
        if (AVAILABLE_PERMISSIONS.containsKey(trimmed)) {
            return true;
        }

        // 检查权限格式（资源.操作）
        if (trimmed.contains(".")) {
            String[] parts = trimmed.split("\\.");
            if (parts.length == 2) {
                String resource = parts[0];
                String action = parts[1];
                return isValidResource(resource) && isValidAction(action);
            }
        }

        // 检查是否为有效的通用权限
        return isValidAction(trimmed) || isValidResource(trimmed);
    }

    /**
     * 获取所有可用的权限列表
     */
    @Override
    public List<String> getAllAvailablePermissions() {
        return new ArrayList<>(AVAILABLE_PERMISSIONS.keySet());
    }

    /**
     * 获取权限的描述信息
     */
    @Override
    public String getPermissionDescription(String permission) {
        return AVAILABLE_PERMISSIONS.getOrDefault(permission, "自定义权限: " + permission);
    }

    /**
     * 验证用户是否有权限分配指定的权限给API Key
     */
    @Override
    public boolean canAssignPermissions(String userId, List<String> permissions) {
        // 这里需要结合用户提供者来验证
        // 简化实现：管理员可以分配所有权限，其他用户只能分配基础权限

        if (permissions == null || permissions.isEmpty()) {
            return true;
        }

        // 检查是否包含管理员权限
        boolean hasAdminPermissions = permissions.stream()
                .anyMatch(p -> p.equals("*") || p.equals("admin") || p.startsWith("admin."));

        if (hasAdminPermissions) {
            // 只有管理员可以分配管理员权限
            return isUserAdmin(userId);
        }

        return true; // 非管理员权限可以被分配
    }

    /**
     * 获取用户可以分配的权限列表
     */
    @Override
    public List<String> getAssignablePermissions(String userId) {
        List<String> assignablePermissions = new ArrayList<>();

        if (isUserAdmin(userId)) {
            // 管理员可以分配所有权限
            assignablePermissions.addAll(AVAILABLE_PERMISSIONS.keySet());
        } else {
            // 普通用户只能分配基础权限
            assignablePermissions.addAll(Arrays.asList(
                    "read", "write", "user.read", "user.write",
                    "api.read", "api.write", "file.read", "file.write"
            ));
        }

        return assignablePermissions;
    }

    /**
     * 根据HTTP方法获取对应的操作类型
     */
    private String getActionByHttpMethod(String httpMethod) {
        if (httpMethod == null) {
            return "read";
        }

        switch (httpMethod.toUpperCase()) {
            case "GET":
            case "HEAD":
            case "OPTIONS":
                return "read";
            case "POST":
            case "PUT":
            case "PATCH":
                return "write";
            case "DELETE":
                return "delete";
            default:
                return "read";
        }
    }

    /**
     * 获取路径对应的权限集合
     */
    private Set<String> getPathPermissions(String requestPath) {
        // 精确匹配
        if (PATH_PERMISSIONS.containsKey(requestPath)) {
            return PATH_PERMISSIONS.get(requestPath);
        }

        // 通配符匹配
        for (Map.Entry<String, Set<String>> entry : PATH_PERMISSIONS.entrySet()) {
            String pattern = entry.getKey();
            if (pattern.endsWith("/*")) {
                String prefix = pattern.substring(0, pattern.length() - 2);
                if (requestPath.startsWith(prefix)) {
                    return entry.getValue();
                }
            }
        }

        return Collections.emptySet();
    }

    /**
     * 从权限系统中提取所有资源名称
     */
    private Set<String> extractResourcesFromPermissions() {
        Set<String> resources = new HashSet<>();

        for (String permission : AVAILABLE_PERMISSIONS.keySet()) {
            if (permission.contains(".")) {
                String resource = permission.substring(0, permission.lastIndexOf("."));
                resources.add(resource);
            }
        }

        return resources;
    }

    /**
     * 验证资源名称是否有效
     */
    private boolean isValidResource(String resource) {
        Set<String> validResources = new HashSet<>();
        validResources.add("user");
        validResources.add("api");
        validResources.add("file");
        validResources.add("admin");
        validResources.add("system");
        return validResources.contains(resource);
    }

    /**
     * 验证操作名称是否有效
     */
    private boolean isValidAction(String action) {
        Set<String> validActions = new HashSet<>();
        validActions.add("read");
        validActions.add("write");
        validActions.add("delete");
        validActions.add("admin");
        validActions.add("create");
        validActions.add("update");
        return validActions.contains(action);
    }

    /**
     * 检查用户是否为管理员（简化实现）
     */
    private boolean isUserAdmin(String userId) {
        // 这里应该调用用户提供者来验证
        // 简化实现：假设admin用户为管理员
        return "admin".equals(userId);
    }

    /**
     * 添加自定义权限
     */
    public void addCustomPermission(String permission, String description) {
        if (isValidPermissionFormat(permission)) {
            AVAILABLE_PERMISSIONS.put(permission, description);
        }
    }

    /**
     * 添加路径权限映射
     */
    public void addPathPermission(String path, Set<String> permissions) {
        if (path != null && permissions != null && !permissions.isEmpty()) {
            PATH_PERMISSIONS.put(path, new HashSet<>(permissions));
        }
    }

    /**
     * 获取权限统计信息
     */
    public Map<String, Object> getPermissionStatistics() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalPermissions", AVAILABLE_PERMISSIONS.size());
        stats.put("pathMappings", PATH_PERMISSIONS.size());
        stats.put("customPermissions", AVAILABLE_PERMISSIONS.size() - getSystemPermissionCount());
        return stats;
    }

    /**
     * 获取系统预定义权限数量
     */
    private int getSystemPermissionCount() {
        return 15; // 系统预定义的权限数量
    }
}